﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Word.Editor.Doc
{
    /// <summary>
    /// The PlcBtePapx structure is a PLC that specifies paragraph, table row, or table cell properties as described later. 
    /// Where most PLCs map CPs to data, the PlcBtePapx maps stream offsets to data instead. 
    /// The offsets in aFC partition a portion of the WordDocument stream into adjacent ranges
    /// </summary>
    public class PlcBtePapx:PLC
    {
        public PlcBtePapx():base()
        { }

        public int DataNo = 0;
        /// <summary>
        /// An array of unsigned integers. 
        /// Each element in this array specifies an offset in the WordDocument stream. 
        /// The elements of aFC MUST be sorted in ascending order, and there MUST NOT be any duplicate entries.
        /// </summary>
        public UInt32[] aFC = null;
        /// <summary>
        /// An array of PnFkpPapx. 
        /// The ith entry in aPnBtePapx is a PnFkpPapx that specifies the properties of all paragraphs, table rows, and table cells whose last character occurs at an offset in the WordDocument stream larger than or equal to aFC[i] but smaller than aFC[i+1]; 
        /// aPnBtePapx MUST contain one less entry than aFC.
        /// </summary>
        public PnFkpPapx[] aPnBtePapx = null;

        public override void ParseBuffer(byte[] buffer)
        {
            base.ParseBuffer(buffer);
            DataNo = (buffer.Length - 4) / 8;
            aFC = new UInt32[DataNo + 1];
            if (DataNo==0)
                throw new IndexOutOfRangeException(Strings.DataArraySize_InvalidValue);
            aPnBtePapx = new PnFkpPapx[DataNo];
            
            for (int i = 0; i < DataNo + 1; i++)
            {
                aFC[i] = GetUint32(buffer, i * 4);
            }
            for (uint i = 0; i < DataNo; i++)
            {
                aPnBtePapx[i] = Readpn(buffer, (DataNo + 1) * 4 + i * 4);
            }
        }

        private PnFkpPapx Readpn(byte[] buffer, long p)
        {
            PnFkpPapx ret = new PnFkpPapx();
            ret.pn = GetUint32(buffer, (int)p);
            ret.pn = (ret.pn << 10) >> 10;
            return ret;
        }

        public override String ToString()
        {
            StringBuilder ret = new StringBuilder();
            for (int i = 0; i < DataNo ; i++)
            {
                ret.AppendFormat("\nCP[{0}]={1:X}-CP[{2}]={3:X}", i, aFC[i], i + 1, aFC[i + 1]);
                ret.AppendFormat("\nPcd[{0}]={1:X}", i, aPnBtePapx[i].pn);
            }
            return ret.ToString();
        }

        internal void AddToTree(System.Windows.Forms.TreeNode PlcBtePapxTN)
        {
            TreeNode aCPTN = PlcBtePapxTN.Nodes.Add("aFC");
            for (int i = 0; i < DataNo + 1; i++)
            {
                aCPTN.Nodes.Add("aFC" + i.ToString(), string.Format("{0}={1:x}", i, aFC[i]));
            }
            TreeNode aPcdTN = PlcBtePapxTN.Nodes.Add("aPnBtePapx");
            for (uint i = 0; i < DataNo; i++)
            {
                aPcdTN.Nodes.Add("aPnBtePapx" + i.ToString(), string.Format("{0}={1:x}", i, aPnBtePapx[i].pn));
            }
        }
    }

    /// <summary>
    /// The PnFkpPapx structure specifies the offset of a PapxFkp in the WordDocument Stream.
    /// length = 32 bits
    /// </summary>
    public class PnFkpPapx
    {
        /// <summary>
        /// An unsigned integer that specifies the offset in the WordDocument Stream of a PapxFkp structure. 
        /// The PapxFkp structure begins at an offset of pn×512.
        /// (22 bits)
        /// </summary>
        public UInt32 pn = 0;
    }
}
